TypeScriptã䜿çšããŠãšã³ã¿ãŒãã©ã€ãºã¢ããªã±ãŒã·ã§ã³ã§åç §ããŒã¿ã广çã«ç®¡çããæ¹æ³ãåŠã³ãŸãããã®å æ¬çãªã¬ã€ãã§ã¯ãenumãconstã¢ãµãŒã·ã§ã³ãããã³ããŒã¿æŽåæ§ãšåå®å šã®ããã®é«åºŠãªãã¿ãŒã³ã«ã€ããŠèª¬æããŸãã
TypeScriptãã¹ã¿ãŒããŒã¿ç®¡çïŒåç §ããŒã¿åãå®è£ ããããã®ã¬ã€ã
ãšã³ã¿ãŒãã©ã€ãºãœãããŠã§ã¢éçºã®è€éãªäžçã§ã¯ãããŒã¿ã¯ããããã¢ããªã±ãŒã·ã§ã³ã®çåœç·ã§ãããã®ããŒã¿ãã©ã®ããã«ç®¡çãä¿åãå©çšãããããã·ã¹ãã ã®å ç¢æ§ãä¿å®æ§ãããã³ã¹ã±ãŒã©ããªãã£ã«çŽæ¥åœ±é¿ããŸãããã®ããŒã¿ã®éèŠãªãµãã»ããã¯ããã¹ã¿ãŒããŒã¿âããžãã¹ã®äžæ žãšãªãéãã©ã³ã¶ã¯ã·ã§ã³ãšã³ãã£ãã£ã§ãããã®é åã§ã¯ãåç §ããŒã¿ãåºç€ãšãªãæ±ãšããŠéç«ã£ãŠããŸãããã®èšäºã§ã¯ãTypeScriptã䜿çšããŠåç §ããŒã¿åãå®è£ ããã³ç®¡çããããã®å æ¬çãªã¬ã€ããéçºè ããã³ã¢ãŒããã¯ãåãã«æäŸãããã°ãäžæŽåã®äžè¬çãªãœãŒã¹ãåå®å šãªæŽåæ§ã®èŠå¡ã«å€ããŸãã
çŸä»£ã®ã¢ããªã±ãŒã·ã§ã³ã§åç §ããŒã¿ç®¡çãéèŠãªçç±
ã³ãŒãã«å ¥ãåã«ãã³ã¢ã³ã³ã»ãããæç¢ºã«çè§£ããŸãããã
ãã¹ã¿ãŒããŒã¿ç®¡çïŒMDMïŒã¯ãããžãã¹ãšITãååããŠããšã³ã¿ãŒãã©ã€ãºã®å ¬åŒå ±æãã¹ã¿ãŒããŒã¿è³ç£ã®åäžæ§ãæ£ç¢ºæ§ãã¹ãã¥ã¯ãŒãã·ãããã»ãã³ãã£ãã¯äžè²«æ§ãããã³èª¬æè²¬ä»»ã確ä¿ãããã¯ãããžãŒå¯Ÿå¿ã®èŠåŸã§ãããã¹ã¿ãŒããŒã¿ã¯ã顧客ã補åãåŸæ¥å¡ãå Žæãªã©ãããžãã¹ã®ãåè©ãã衚ããŸãã
åç §ããŒã¿ã¯ãä»ã®ããŒã¿ãåé¡ãŸãã¯ã«ããŽãªåããããã«äœ¿çšããããã¹ã¿ãŒããŒã¿ã®ç¹å®ã®ã¿ã€ãã§ããéåžžãéçã§ããããæéã®çµéãšãšãã«éåžžã«ãã£ãããšå€åããŸããç¹å®ã®ãã£ãŒã«ããåãåŸãå®çŸ©æžã¿ã®å€ã®ã»ãããšèããŠãã ãããäžçäžã®äžè¬çãªäŸã以äžã«ç€ºããŸãã
- åœãªã¹ãïŒäŸïŒã¢ã¡ãªã«åè¡åœããã€ããæ¥æ¬ïŒ
 - é貚ã³ãŒãïŒUSDãEURãJPYïŒ
 - 泚æã¹ããŒã¿ã¹ïŒä¿çäžãåŠçäžãçºéæžã¿ãé éæžã¿ããã£ã³ã»ã«æžã¿ïŒ
 - ãŠãŒã¶ãŒããŒã«ïŒç®¡çè ãç·šéè ãé²èЧè ïŒ
 - 補åã«ããŽãªïŒãšã¬ã¯ãããã¯ã¹ãã¢ãã¬ã«ãæžç±ïŒ
 
åç §ããŒã¿ã®èª²é¡ã¯ãã®è€éãã§ã¯ãªãããã®æ®åæ§ã«ãããŸããããŒã¿ããŒã¹ãAPIãã€ããŒããããžãã¹ããžãã¯ãããã³ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã®ããããå Žæã«è¡šç€ºãããŸãã管çãäžååãªå ŽåãããŒã¿ã®äžè²«æ§ã®æ¬ åŠãã©ã³ã¿ã€ã ãšã©ãŒãããã³ä¿å®ãšãªãã¡ã¯ã¿ãªã³ã°ãå°é£ãªã³ãŒãããŒã¹ãªã©ãåé¡ãé£éçã«çºçããŸããããã¯ã匷åãªéçåã·ã¹ãã ãåããTypeScriptããéçºæ®µéã§ããŒã¿ã¬ããã³ã¹ã匷å¶ããããã®äžå¯æ¬ ãªããŒã«ãšãªãå Žæã§ãã
ã³ã¢åé¡ïŒãããžãã¯ã¹ããªã³ã°ãã®å±éºæ§
äžè¬çãªã·ããªãªã§ããåœéçãªeã³ããŒã¹ãã©ãããã©ãŒã ã§åé¡ã説æããŸããããã·ã¹ãã ã¯æ³šæã®ã¹ããŒã¿ã¹ã远跡ããå¿ èŠããããŸãããã€ãŒããªå®è£ ã§ã¯ãã³ãŒãã§çã®æååãçŽæ¥äœ¿çšããå ŽåããããŸãã
            
function processOrder(orderId: number, newStatus: string) {
  if (newStatus === 'shipped') {
    // Logic for shipping
    console.log(`Order ${orderId} has been shipped.`);
  } else if (newStatus === 'delivered') {
    // Logic for delivery confirmation
    console.log(`Order ${orderId} confirmed as delivered.`);
  } else if (newStatus === 'pending') {
    // ...and so on
  }
}
// Somewhere else in the application...
processOrder(12345, 'Shipped'); // Uh oh, a typo!
            
          
        ãã®ã¢ãããŒãã¯ããã°ãã°ãããžãã¯ã¹ããªã³ã°ããšåŒã°ãããã®ã«äŸåããŠãããå±éºã«æºã¡ãŠããŸãã
- ã¿ã€ããã¹ïŒäžèšã®ããã«ã`shipped` vs. `Shipped`ã¯ãæ€åºãé£ãã埮åŠãªãã°ãåŒãèµ·ããå¯èœæ§ããããŸããã³ã³ãã€ã©ã¯äœãæ¯æŽããŸããã
 - çºèŠå¯èœæ§ã®æ¬ åŠïŒæ°ããéçºè ã¯ãæå¹ãªã¹ããŒã¿ã¹ãäœã§ããããç°¡åã«ç¥ãæ¹æ³ããããŸãããèãããããã¹ãŠã®æååå€ãèŠã€ããããã«ãã³ãŒãããŒã¹å šäœãæ€çŽ¢ããå¿ èŠããããŸãã
 - ã¡ã³ããã³ã¹ã®æªå€¢ïŒããžãã¹ããshippedãããdispatchedãã«å€æŽããããšã«ããå Žåã¯ã©ãã§ããããïŒã€ã³ã¹ã¿ã³ã¹ãèŠéããããé¢ä¿ã®ãªããã®ã誀ã£ãŠå€æŽãããããªãããšãæåŸ ããŠããªã¹ã¯ã®é«ããããžã§ã¯ãå šäœã®æ€çŽ¢ãšçœ®æãå®è¡ããå¿ èŠããããŸãã
 - ä¿¡é Œã§ããå¯äžã®æ å ±æºããªãïŒæå¹ãªå€ã¯ã¢ããªã±ãŒã·ã§ã³å šäœã«æ£ãã°ã£ãŠãããããã³ããšã³ããããã¯ãšã³ããããã³ããŒã¿ããŒã¹éã§æœåšçãªäžæŽåãçºçããå¯èœæ§ããããŸãã
 
ç§ãã¡ã®ç®æšã¯ãåç §ããŒã¿ã®åäžã®ä¿¡é Œã§ãããœãŒã¹ãäœæããTypeScriptã®åã·ã¹ãã ãæŽ»çšããŠããã®æ£ããäœ¿çšæ³ãããããå Žæã§åŒ·å¶ããããšã«ããããããã®åé¡ãæé€ããããšã§ãã
åç §ããŒã¿ã®åºæ¬çãªTypeScriptãã¿ãŒã³
TypeScriptã¯ãåç §ããŒã¿ã管çããããã®ããã€ãã®åªãããã¿ãŒã³ãæäŸããŠãããããããã«ç¬èªã®ãã¬ãŒããªãããããŸããå€å žçãªãã®ããææ°ã®ãã¹ããã©ã¯ãã£ã¹ãŸã§ãæãäžè¬çãªãã®ãæ¢ããŸãããã
ã¢ãããŒã1ïŒå€å žçãª`enum`
JavaãC#ãªã©ã®èšèªããæ¥ãå€ãã®éçºè ã«ãšã£ãŠã`enum`ã¯ãã®ãžã§ãã«æã銎æã¿ã®ããããŒã«ã§ããååä»ã宿°ã®ã»ãããå®çŸ©ã§ããŸãã
            
export enum OrderStatus {
  Pending = 'PENDING',
  Processing = 'PROCESSING',
  Shipped = 'SHIPPED',
  Delivered = 'DELIVERED',
  Cancelled = 'CANCELLED',
}
function processOrder(orderId: number, newStatus: OrderStatus) {
  if (newStatus === OrderStatus.Shipped) {
    console.log(`Order ${orderId} has been shipped.`);
  }
}
processOrder(123, OrderStatus.Shipped); // Correct and type-safe
// processOrder(123, 'SHIPPED'); // Compile-time error! Great!
            
          
        å©ç¹ïŒ
- æç¢ºãªæå³ïŒé¢é£ãã宿°ã®ã»ãããå®çŸ©ããŠããããšãæç€ºçã«ç€ºããŠããŸããåå`OrderStatus`ã¯éåžžã«èšè¿°çã§ãã
 - åç®åä»ãïŒ`OrderStatus.Shipped`ã¯åãªãæååãSHIPPEDãã§ã¯ãããŸããã`OrderStatus`ã®åã§ããããã«ãããäžéšã®ã·ããªãªã§ãã匷åãªåãã§ãã¯ãæäŸã§ããŸãã
 - èªã¿ãããïŒ`OrderStatus.Shipped`ã¯ãçã®æååãããèªã¿ããããšèŠãªãããããšããããããŸãã
 
çæïŒ
- JavaScriptãããããªã³ãïŒTypeScriptã®enumã¯ãã³ã³ãã€ã«æã®æ§é ã ãã§ã¯ãããŸãããã³ã³ãã€ã«ãããåºåã§JavaScriptãªããžã§ã¯ãïŒImmediately Invoked Function ExpressionããŸãã¯IIFEïŒãçæãããã³ãã«ãµã€ãºã倧ããããŸãã
 - æ°å€Enumã®è€éãïŒããã§ã¯æååenumã䜿çšããŸãããïŒããã¯æšå¥šããããã©ã¯ãã£ã¹ã§ãïŒãTypeScriptã®ããã©ã«ãã®æ°å€enumã¯ãæ··ä¹±ãæãéãããã³ã°åäœãããå¯èœæ§ããããŸãã
 - æè»æ§ã®äœäžïŒè¿œå ã®äœæ¥ãªãã«ãenumããå ±çšäœåãæŽŸçãããããããè€éãªããŒã¿æ§é ã«äœ¿çšãããããããšã¯å°é£ã§ãã
 
ã¢ãããŒã2ïŒè»œéæååãªãã©ã«å ±çšäœ
ãã軜éã§çŽç²ãªåã¬ãã«ã®ã¢ãããŒãã¯ãæååãªãã©ã«ã®å ±çšäœã䜿çšããããšã§ãããã®ãã¿ãŒã³ã¯ãç¹å®ã®æååã®ã»ããã®ããããã§ããå¯èœæ§ã®ããåãå®çŸ©ããŸãã
            
export type OrderStatus =
  | 'PENDING'
  | 'PROCESSING'
  | 'SHIPPED'
  | 'DELIVERED'
  | 'CANCELLED';
function processOrder(orderId: number, newStatus: OrderStatus) {
  if (newStatus === 'SHIPPED') {
    console.log(`Order ${orderId} has been shipped.`);
  }
}
processOrder(123, 'SHIPPED'); // Correct and type-safe
// processOrder(123, 'shipped'); // Compile-time error! Awesome!
            
          
        å©ç¹ïŒ
- ãŒãJavaScriptãããããªã³ãïŒ`type`å®çŸ©ã¯ã³ã³ãã€ã«äžã«å®å šã«æ¶å»ãããŸãããããã¯TypeScriptã³ã³ãã€ã©å°çšã«ååšããããã¯ãªãŒã³ã§å°ããªJavaScriptã«ãªããŸãã
 - ã·ã³ãã«ãïŒæ§æã¯ç°¡åã§çè§£ããããã§ãã
 - åªãããªãŒãã³ã³ããªãŒãïŒã³ãŒããšãã£ã¿ãŒã¯ããã®åã®å€æ°ã«å¯ŸããŠåªãããªãŒãã³ã³ããªãŒããæäŸããŸãã
 
çæïŒ
- ã©ã³ã¿ã€ã ææç©ãªãïŒããã¯é·æã§ãããçæã§ããããŸããåã®ã¿ã§ãããããã©ã³ã¿ã€ã ã§èããããå€ãå埩åŠçããããšã¯ã§ããŸããïŒããšãã°ãããããããŠã³ã¡ãã¥ãŒã«å ¥åããããïŒãæ å ±ã®éè€ã«ã€ãªãã宿°ã®å¥ã®é åãå®çŸ©ããå¿ èŠããããŸãã
 
            
// Duplication of values
export type OrderStatus = 'PENDING' | 'PROCESSING' | 'SHIPPED';
export const ALL_ORDER_STATUSES = ['PENDING', 'PROCESSING', 'SHIPPED'];
            
          
        ãã®éè€ã¯ãDon't Repeat YourselfïŒDRYïŒååã®æãããªéåã§ãããåãšé åãåæããªããªã£ãå Žåã«ãã°ã®æœåšçãªåå ãšãªããŸããããã«ãããçŸä»£ã®æšå¥šãããã¢ãããŒãã«ã€ãªãããŸãã
ã¢ãããŒã3ïŒ`const`ã¢ãµãŒã·ã§ã³ã®ãã¯ãŒãã¬ã€ïŒãŽãŒã«ãã¹ã¿ã³ããŒãïŒ
TypeScript 3.4ã§å°å ¥ããã`as const`ã¢ãµãŒã·ã§ã³ã¯ãå®ç§ãªãœãªã¥ãŒã·ã§ã³ãæäŸããŸããã©ã³ã¿ã€ã ã«ååšããåäžã®ä¿¡é Œã§ããæ å ±æºãšãã³ã³ãã€ã«æã«ååšããå®å šã«åä»ããããæŽŸçå ±çšäœã®äž¡æ¹ã®æé«ã®çµã¿åããã§ãã
ãã¿ãŒã³ã¯æ¬¡ã®ãšããã§ãã
            
// 1. Define the runtime data with 'as const'
export const ORDER_STATUSES = [
  'PENDING',
  'PROCESSING',
  'SHIPPED',
  'DELIVERED',
  'CANCELLED',
] as const;
// 2. Derive the type from the runtime data
export type OrderStatus = typeof ORDER_STATUSES[number];
//   ^? type OrderStatus = "PENDING" | "PROCESSING" | "SHIPPED" | "DELIVERED" | "CANCELLED"
// 3. Use it in your functions
function processOrder(orderId: number, newStatus: OrderStatus) {
  if (newStatus === 'SHIPPED') {
    console.log(`Order ${orderId} has been shipped.`);
  }
}
// 4. Use it at runtime AND compile time
processOrder(123, 'SHIPPED'); // Type-safe!
// And you can easily iterate over it for UIs!
function getStatusOptions() {
  return ORDER_STATUSES.map(status => ({ value: status, label: status.toLowerCase() }));
}
            
          
        ãããéåžžã«åŒ·åãªçç±ãåæããŸãããã
- `as const`ã¯ãTypeScriptã«å¯èœãªéãæãå ·äœçãªåãæšè«ããããã«æç€ºããŸãã`string[]`ã®ä»£ããã«ãåã`readonly ['PENDING', 'PROCESSING', ...]`ãšããŠæšè«ããŸãã`readonly`修食åã¯ãé åã®å¶çºçãªå€æŽãé²ããŸãã
 - `typeof ORDER_STATUSES[number]`ã¯ãåãæŽŸçãããããžãã¯ã§ããããã¯ãã`ORDER_STATUSES`é åå ã®èŠçŽ ã®åãååŸãããããšãæå³ããŸããTypeScriptã¯ãç¹å®ã®æååãªãã©ã«ãèªèãããããããå ±çšäœåãäœæããã®ã«ååãªã»ã©ã¹ããŒãã§ãã
 - åäžã®ä¿¡é Œã§ããæ å ±æºïŒSSOTïŒïŒ`ORDER_STATUSES`é åã¯ããããã®å€ãå®çŸ©ãããŠããå¯äžã®å Žæã§ããåã¯ããããèªåçã«æŽŸçããŸããé åã«æ°ããã¹ããŒã¿ã¹ã远å ãããšã`OrderStatus`åãèªåçã«æŽæ°ãããŸããããã«ãããåãšã©ã³ã¿ã€ã å€ãéåæã«ãªãå¯èœæ§ããªããªããŸãã
 
ãã®ãã¿ãŒã³ã¯ãTypeScriptã§åçŽãªåç §ããŒã¿ãåŠçããããã®çŸä»£çã§æ £çšçã§å ç¢ãªæ¹æ³ã§ãã
é«åºŠãªå®è£ ïŒè€éãªåç §ããŒã¿ã®æ§é å
åç §ããŒã¿ã¯ãåçŽãªæååã®ãªã¹ããããè€éãªããšããããããŸããé éãã©ãŒã ã®åœãªã¹ãã®ç®¡çãæ€èšããŠãã ãããååœã«ã¯ãååã2æåã®ISOã³ãŒããããã³ãã€ã€ã«ã³ãŒãããããŸãã`as const`ãã¿ãŒã³ã¯ãããã«å¯ŸããŠçŸããæ¡åŒµã§ããŸãã
ããŒã¿ã³ã¬ã¯ã·ã§ã³ã®å®çŸ©ãšä¿å
ãŸããåäžã®ä¿¡é Œã§ããæ å ±æºãäœæããŸãããªããžã§ã¯ãã®é åã§ãã`as const`ãé©çšããŠãæ§é å šäœãå®å šã«èªã¿åãå°çšã«ããæ£ç¢ºãªåæšè«ãå¯èœã«ããŸãã
            
export const COUNTRIES = [
  {
    code: 'US',
    name: 'United States of America',
    dial: '+1',
    continent: 'North America',
  },
  {
    code: 'DE',
    name: 'Germany',
    dial: '+49',
    continent: 'Europe',
  },
  {
    code: 'IN',
    name: 'India',
    dial: '+91',
    continent: 'Asia',
  },
  {
    code: 'BR',
    name: 'Brazil',
    dial: '+55',
    continent: 'South America',
  },
] as const;
            
          
        ã³ã¬ã¯ã·ã§ã³ããæ£ç¢ºãªåãæŽŸçããã
ããã§ããã®ããŒã¿æ§é ããçŽæ¥ãéåžžã«æçšã§å ·äœçãªåãæŽŸçãããããšãã§ããŸãã
            
// Derive the type for a single country object
export type Country = typeof COUNTRIES[number];
/*
  ^? type Country = {
      readonly code: "US";
      readonly name: "United States of America";
      readonly dial: "+1";
      readonly continent: "North America";
  } | {
      readonly code: "DE";
      ...
  }
*/
// Derive a union type of all valid country codes
export type CountryCode = Country['code']; // or `typeof COUNTRIES[number]['code']`
//   ^? type CountryCode = "US" | "DE" | "IN" | "BR"
// Derive a union type of all continents
export type Continent = Country['continent'];
//   ^? type Continent = "North America" | "Europe" | "Asia" | "South America"
            
          
        ããã¯ä¿¡ããããªãã»ã©åŒ·åã§ããåé·ãªåå®çŸ©ã1è¡ãèšè¿°ããã«ã次ã®ãã®ãäœæããŸããã
- åœãªããžã§ã¯ãã®åœ¢ç¶ã衚ã`Country`åã
 - 倿°ãŸãã¯é¢æ°ãã©ã¡ãŒã¿ãŒãæå¹ãªæ¢åã®åœã³ãŒãã®1ã€ã®ã¿ã§ããããšãä¿èšŒãã`CountryCode`åã
 - åœãåé¡ãã`Continent`åã
 
`COUNTRIES`é åã«æ°ããåœã远å ãããšããããã®åã¯ãã¹ãŠèªåçã«æŽæ°ãããŸããããã¯ãã³ã³ãã€ã©ã«ãã£ãŠåŒ·å¶ãããããŒã¿æŽåæ§ã§ãã
éäžååç §ããŒã¿ãµãŒãã¹ã®æ§ç¯
ã¢ããªã±ãŒã·ã§ã³ãæé·ããã«ã€ããŠããã®åç §ããŒã¿ãžã®ã¢ã¯ã»ã¹ãéäžåããããšããå§ãããŸããããã¯ãåçŽãªã¢ãžã¥ãŒã«ãŸãã¯ããæ£åŒãªãµãŒãã¹ã¯ã©ã¹ãéããŠè¡ãããšãã§ããŸããéåžžãã·ã³ã°ã«ãã³ãã¿ãŒã³ã䜿çšããŠå®è£ ãããã¢ããªã±ãŒã·ã§ã³å šäœã§åäžã®ã€ã³ã¹ã¿ã³ã¹ãä¿èšŒããŸãã
ã¢ãžã¥ãŒã«ããŒã¹ã®ã¢ãããŒã
ã»ãšãã©ã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãããŒã¿ãšããã€ãã®ãŠãŒãã£ãªãã£é¢æ°ããšã¯ã¹ããŒãããåçŽãªã¢ãžã¥ãŒã«ã§ååã§ããããšã¬ã¬ã³ãã§ãã
            
// file: src/services/referenceData.ts
// ... (our COUNTRIES constant and derived types from above)
export const getCountries = () => COUNTRIES;
export const getCountryByCode = (code: CountryCode): Country | undefined => {
  // The 'find' method is perfectly type-safe here
  return COUNTRIES.find(country => country.code === code);
};
export const getCountriesByContinent = (continent: Continent): Country[] => {
  return COUNTRIES.filter(country => country.continent === continent);
};
// You can also export the raw data and types if needed
export { COUNTRIES, Country, CountryCode, Continent };
            
          
        ãã®ã¢ãããŒãã¯ãã¯ãªãŒã³ã§ãã¹ãå¯èœã§ãããESã¢ãžã¥ãŒã«ãå©çšããŠèªç¶ãªã·ã³ã°ã«ãã³ã©ã€ã¯ãªåäœãå®çŸããŸããã¢ããªã±ãŒã·ã§ã³ã®ã©ã®éšåã§ãããããã®é¢æ°ãã€ã³ããŒãããŠãåç §ããŒã¿ãžã®äžè²«ããã¿ã€ãã»ãŒããªã¢ã¯ã»ã¹ãååŸã§ããŸãã
éåæçã«ããŒããããåç §ããŒã¿ã®åŠç
å€ãã®çŸå®äžçã®ãšã³ã¿ãŒãã©ã€ãºã·ã¹ãã ã§ã¯ãåç §ããŒã¿ã¯ããã³ããšã³ãã«ããŒãã³ãŒããããŠããŸããããã¹ãŠã®ã¯ã©ã€ã¢ã³ãã§åžžã«ææ°ã®ç¶æ ã«ãªãããã«ãããã¯ãšã³ãAPIãããã§ãããããŸããTypeScriptãã¿ãŒã³ã¯ããããèæ ®ããå¿ èŠããããŸãã
éèŠãªã®ã¯ãäºæ³ãããAPIå¿çã«åãããŠã¯ã©ã€ã¢ã³ãåŽã§åãå®çŸ©ããããšã§ããæ¬¡ã«ãZodãio-tsãªã©ã®ã©ã³ã¿ã€ã æ€èšŒã©ã€ãã©ãªã䜿çšããŠãAPIå¿çãå®éã«ã©ã³ã¿ã€ã ã§åã«æºæ ããŠããããšã確èªããAPIã®åçãªæ§è³ªãšTypeScriptã®éçãªäžçã®ã®ã£ãããåããŸãã
            
import { z } from 'zod';
// 1. Define the schema for a single country using Zod
const CountrySchema = z.object({
  code: z.string().length(2),
  name: z.string(),
  dial: z.string(),
  continent: z.string(),
});
// 2. Define the schema for the API response (an array of countries)
const CountriesApiResponseSchema = z.array(CountrySchema);
// 3. Infer the TypeScript type from the Zod schema
export type Country = z.infer;
// We can still get a code type, but it will be 'string' since we don't know the values ahead of time.
// If the list is small and fixed, you can use z.enum(['US', 'DE', ...]) for more specific types.
export type CountryCode = Country['code'];
// 4. A service to fetch and cache the data
class ReferenceDataService {
  private countries: Country[] | null = null;
  async fetchAndCacheCountries(): Promise {
    if (this.countries) {
      return this.countries;
    }
    const response = await fetch('/api/v1/countries');
    const jsonData = await response.json();
    // Runtime validation!
    const validationResult = CountriesApiResponseSchema.safeParse(jsonData);
    if (!validationResult.success) {
      console.error('Invalid country data from API:', validationResult.error);
      throw new Error('Failed to load reference data.');
    }
    this.countries = validationResult.data;
    return this.countries;
  }
}
export const referenceDataService = new ReferenceDataService();
  
            
          
        ãã®ã¢ãããŒãã¯éåžžã«å ç¢ã§ããæšè«ãããTypeScriptåã«ããã³ã³ãã€ã«æå®å šæ§ãšãå€éšãœãŒã¹ããã®ããŒã¿ãäºæ³ããã圢ç¶ãšäžèŽããããšã確èªããããšã«ããã©ã³ã¿ã€ã å®å šæ§ãæäŸããŸããã¢ããªã±ãŒã·ã§ã³ã¯èµ·åæã«`referenceDataService.fetchAndCacheCountries()`ãåŒã³åºããŠãå¿ èŠãªãšãã«ããŒã¿ã確å®ã«å©çšã§ããããã«ããããšãã§ããŸãã
ã¢ããªã±ãŒã·ã§ã³ãžã®åç §ããŒã¿ã®çµ±å
匷åºãªåºç€ãæ§ç¯ããããšã§ããã®ã¿ã€ãã»ãŒããªåç §ããŒã¿ãã¢ããªã±ãŒã·ã§ã³å šäœã§äœ¿çšããããšãç°¡åãã€ãšã¬ã¬ã³ãã«ãªããŸãã
UIã³ã³ããŒãã³ãïŒäŸïŒReactïŒ
åœãéžæããããã®ããããããŠã³ã³ã³ããŒãã³ããæ€èšããŠãã ããã以åã«æŽŸçããåã«ãããã³ã³ããŒãã³ãã®ãããããæç€ºçãã€å®å šã«ãªããŸãã
            
import React from 'react';
import { COUNTRIES, CountryCode } from '../services/referenceData';
interface CountrySelectorProps {
  selectedValue: CountryCode | null;
  onChange: (newCode: CountryCode) => void;
}
export const CountrySelector: React.FC = ({ selectedValue, onChange }) => {
  return (
    
  );
};
 
            
          
        ããã§ãTypeScriptã¯`selectedValue`ãæå¹ãª`CountryCode`ã§ããå¿ èŠãããã`onChange`ã³ãŒã«ããã¯ãåžžã«æå¹ãª`CountryCode`ãåãåãããšãä¿èšŒããŸãã
ããžãã¹ããžãã¯ããã³APIã¬ã€ã€ãŒ
åã¯ãç¡å¹ãªããŒã¿ãã·ã¹ãã å šäœã«äŒæããã®ãé²ããŸãããã®ããŒã¿ãæäœãã颿°ã¯ãã¹ãŠã远å ãããå®å šæ§ããæ©æµãåããŸãã
            
import { OrderStatus } from '../services/referenceData';
interface Order {
  id: string;
  status: OrderStatus;
  items: any[];
}
// This function can only be called with a valid status.
function canCancelOrder(order: Order): boolean {
  // No need to check for typos like 'pendng' or 'Procesing'
  return order.status === 'PENDING' || order.status === 'PROCESSING';
}
const myOrder: Order = { id: 'xyz', status: 'SHIPPED', items: [] };
if (canCancelOrder(myOrder)) {
  // This block is correctly (and safely) not executed.
}
            
          
        åœéåïŒi18nïŒã®å Žå
åç §ããŒã¿ã¯ãåœéåã®éèŠãªèŠçŽ ã§ããããšããããããŸããããŒã¿ã¢ãã«ãæ¡åŒµããŠã翻蚳ããŒãå«ããããšãã§ããŸãã
            
export const ORDER_STATUSES = [
  { code: 'PENDING', i18nKey: 'orderStatus.pending' },
  { code: 'PROCESSING', i18nKey: 'orderStatus.processing' },
  { code: 'SHIPPED', i18nKey: 'orderStatus.shipped' },
] as const;
export type OrderStatusCode = typeof ORDER_STATUSES[number]['code'];
            
          
        UIã³ã³ããŒãã³ãã¯ã`i18nKey`ã䜿çšããŠããŠãŒã¶ãŒã®çŸåšã®ãã±ãŒã«ã®ç¿»èš³ãããæååãæ€çŽ¢ã§ããŸãããããžãã¹ããžãã¯ã¯åŒãç¶ãå®å®ãã倿Žãããªã`code`ã§åäœããŸãã
ã¬ããã³ã¹ãšã¡ã³ããã³ã¹ã®ãã¹ããã©ã¯ãã£ã¹
ãããã®ãã¿ãŒã³ã®å®è£ ã¯çŽ æŽãããã¹ã¿ãŒãã§ãããé·æçãªæåã«ã¯åªããã¬ããã³ã¹ãå¿ èŠã§ãã
- åäžã®ä¿¡é Œã§ããæ å ±æºïŒSSOTïŒïŒããã¯æãéèŠãªååã§ãããã¹ãŠã®åç §ããŒã¿ã¯ã1ã€ã ãã®äžæã®ä¿¡é Œã§ããæ å ±æºããçºçããå¿ èŠããããŸããããã³ããšã³ãã¢ããªã±ãŒã·ã§ã³ã®å Žåãããã¯åäžã®ã¢ãžã¥ãŒã«ãŸãã¯ãµãŒãã¹ã§ããå¯èœæ§ããããŸããå€§èŠæš¡ãªãšã³ã¿ãŒãã©ã€ãºã§ã¯ãããã¯å€ãã®å ŽåãAPIãä»ããŠããŒã¿ãå ¬éãããå°çšã®MDMã·ã¹ãã ã§ãã
 - æç¢ºãªæææš©ïŒåç §ããŒã¿ã®æ£ç¢ºæ§ãšæŽåæ§ãç¶æãã責任ãè² ãããŒã ãŸãã¯å人ãæå®ããŸãã倿Žã¯æå³çã§ååã«ææžåãããŠããå¿ èŠããããŸãã
 - ããŒãžã§ã³ç®¡çïŒåç §ããŒã¿ãAPIããããŒããããå Žåã¯ãAPIãšã³ããã€ã³ããããŒãžã§ã³ç®¡çããŸããããã«ãããããŒã¿æ§é ã®ç Žå£çãªå€æŽãå€ãã¯ã©ã€ã¢ã³ãã«åœ±é¿ãäžããã®ãé²ããŸãã
 - ããã¥ã¡ã³ãïŒJSDocãŸãã¯ãã®ä»ã®ããã¥ã¡ã³ãããŒã«ã䜿çšããŠãååç §ããŒã¿ã»ããã®æå³ãšäœ¿çšæ³ã説æããŸããããšãã°ãå`OrderStatus`ã®èåŸã«ããããžãã¹ã«ãŒã«ãææžåããŸãã
 - ã³ãŒãçæã®æ€èšïŒããã¯ãšã³ããšããã³ããšã³ãéã®ç©¶æ¥µã®åæã®ããã«ãããã¯ãšã³ãAPI仿§ïŒäŸïŒOpenAPI/SwaggerïŒããçŽæ¥TypeScriptåãçæããããŒã«ã®äœ¿çšãæ€èšããŠãã ãããããã«ãããã¯ã©ã€ã¢ã³ãåŽã®åãAPIã®ããŒã¿æ§é ãšåæãããããã»ã¹ãèªååãããŸãã
 
çµè«ïŒTypeScriptã«ããããŒã¿æŽåæ§ã®åäž
ãã¹ã¿ãŒããŒã¿ç®¡çã¯ãã³ãŒããã¯ããã«è¶ ããèŠåŸã§ãããéçºè ãšããŠãç§ãã¡ã¯ã¢ããªã±ãŒã·ã§ã³å ã®ããŒã¿æŽåæ§ã®æçµçãªã²ãŒãããŒããŒã§ããè匱ãªãããžãã¯ã¹ããªã³ã°ãããé¢ããææ°ã®TypeScriptãã¿ãŒã³ãæ¡çšããããšã§ãäžè¬çãªãã°ã®ã¯ã©ã¹å šäœã广çã«æé€ã§ããŸãã
åæšè«ãšçµã¿åããã`as const`ãã¿ãŒã³ã¯ãåç §ããŒã¿ã管çããããã®å ç¢ã§ä¿å®å¯èœã§ãšã¬ã¬ã³ããªãœãªã¥ãŒã·ã§ã³ãæäŸããŸããã©ã³ã¿ã€ã ããžãã¯ãšã³ã³ãã€ã«æåãã§ãã«ãŒã®äž¡æ¹ãæäŸããåäžã®ä¿¡é Œã§ããæ å ±æºã確ç«ããäž¡è ãåæããªããªãããšã¯ãããŸãããéäžåãµãŒãã¹ããã³å€éšããŒã¿ã®ã©ã³ã¿ã€ã æ€èšŒãšçµã¿åãããããšã§ããã®ã¢ãããŒãã¯ãå埩åã®ãããšã³ã¿ãŒãã©ã€ãºã°ã¬ãŒãã®ã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®åŒ·åãªãã¬ãŒã ã¯ãŒã¯ãäœæããŸãã
æçµçã«ãTypeScriptã¯`null`ãŸãã¯`undefined`ãšã©ãŒãé²ãããã®åãªãããŒã«ã§ã¯ãããŸãããããŒã¿ã¢ããªã³ã°ã®ããã®åŒ·åãªèšèªã§ãããããžãã¹ã«ãŒã«ãã³ãŒãã®æ§é ã«çŽæ¥çµã¿èŸŒãããã®èšèªã§ããåç §ããŒã¿ç®¡çã®ããã«ãã®å¯èœæ§ãæå€§éã«æŽ»çšããããšã§ããã匷åã§äºæž¬å¯èœã§ããããããã§ãã·ã§ãã«ãªãœãããŠã§ã¢è£œåãæ§ç¯ã§ããŸãã